package com.lenovo.lmrp.base;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.Inject;
import com.lenovo.sdc.framework.net.FTPCommand;
import com.lenovo.sdc.framework.net.FTPHelper;
import com.lenovo.sdc.framework.util.AttributeBean;
import com.lenovo.sdc.framework.util.Tuple;
import com.lenovo.sdc.framework.util.Tuple.Pair;
import com.lenovo.sdc.framework.util.exception.ErrorCode;
import com.lenovo.sdc.framework.util.exception.TraceableException;

public class FTPService implements IFileService {
    private static final Logger logger = LoggerFactory.getLogger(FTPService.class);
    private AttributeBean params;
    private FTPHelper ftpHelper;

    @Inject
    public FTPService(AttributeBean params) {
        this.params = params;
        
        AttributeBean ftpParams = new AttributeBean();
        ftpParams.addAttribute("ftp.server.ip", params.get(ParamNameDef.FILE_SERVER_HOST));
        ftpParams.addAttribute("ftp.server.port", params.get(ParamNameDef.FILE_SERVER_PORT));
        ftpParams.addAttribute("ftp.server.username", params.get(ParamNameDef.FILE_SERVER_USER));
        ftpParams.addAttribute("ftp.server.password", params.get(ParamNameDef.FILE_SERVER_PASSWD));
        ftpParams.addAttribute("ftp.server.workpath", params.get(ParamNameDef.FILE_ROOT_PATH));
        ftpParams.addAttribute("ftp.server.mode", params.get(ParamNameDef.FILE_SERVER_FTPMODE));
        ftpParams.addAttribute("ftp.server.encoding", params.get(ParamNameDef.FILE_SERVER_ENCODING));
        
        ftpHelper = new FTPHelper(ftpParams);
    }

    public Pair<String, Long> writeFile(String relativePath, byte[] data) {
        return writeFile(relativePath, new ByteArrayInputStream(data));
    }

    public Pair<String, Long> writeFile(String relativePath, InputStream in) {
        String root = params.getAttribute("file.rootpath", "data");
        String path = relativePath.replace('\\', '/');
        if (path.startsWith("/")) {
            if (root.endsWith("/"))
                path = root + path.substring(1);
            else
                path = root + path;
        }
        else {
            if (root.endsWith("/"))
                path = root + path;
            else
                path = root + "/" + path;
        }
        
        String fileName = null;
        int pos = path.lastIndexOf("/");
        fileName = path.substring(pos + 1);
        path = path.substring(0,  pos);
        
        Map<String, InputStream> fileStream = new HashMap<String, InputStream>();
        fileStream.put(fileName, in);
        try {
            FTPCommand command = ftpHelper.createPutStreamCmd(fileStream, path);
            ftpHelper.execute(new FTPCommand[]{command});
            return Tuple.makePair(path + "/" + fileName, command.getLength());
        }
        catch (Exception exp) {
            throw new TraceableException(ErrorCode.FILE_WRITE_FAILED, exp);
        }
    }

    public long readFile(String absolutePath, StringBuilder buf) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        Map<String, OutputStream> remoteFiles = new HashMap<>();
        remoteFiles.put(absolutePath, out);
        
        try {
            FTPCommand command = ftpHelper.createGetFileStreamCmd(remoteFiles);
            ftpHelper.execute(new FTPCommand[]{command});
            buf.append(out.toString("UTF-8"));
            return command.getLength();
        }
        catch (Exception exp) {
            throw new TraceableException(ErrorCode.FILE_ERROR, exp);
        }
    }

    public long readFile(String absolutePath, ByteBuffer buf) {
        return 0;
    }

    public long readFile(String absolutePath, OutputStream out) {
        Map<String, OutputStream> remoteFiles = new HashMap<>();
        remoteFiles.put(absolutePath, out);
        
        try {
            FTPCommand command = ftpHelper.createGetFileStreamCmd(remoteFiles);
            ftpHelper.execute(new FTPCommand[]{command});
            return command.getLength();
        }
        catch (Exception exp) {
            throw new TraceableException(ErrorCode.FILE_ERROR, exp);
        }
    }
}
